'use strict';
const ActualListeners = {};
const TargetListeners = {};
const fiipCloudVarLists = {};

function memcmp(dst, src, len) {
  for (let i = 0; i < len; i++) {
    if (dst[i] !== src[i]) {
      return -1;
    }
  }
  return 0;
}

function fiipCloudVar_init() {}

function fiipCloudVar_onActualChange(id, kVal, kLen, fun) {
  const listener = ActualListeners[id + kVal];
  if (listener) {
    listener.fun = fun;
  } else {
    ActualListeners[id + kVal] = { id, kLen, kVal, fun };
  }
}
function fiipCloudVar_onTargetChange(id, kVal, kLen, fun) {
  const listener = TargetListeners[id + kVal];
  if (listener) {
    listener.fun = fun;
  } else {
    TargetListeners[id + kVal] = { id, kLen, kVal, fun };
  }
}
function fiipCloudVar_getVarList(id) {
  if (!fiipCloudVarLists[id]) {
    fiipCloudVarLists[id] = {};
  }
  return fiipCloudVarLists[id];
}
function fiipCloudVar_get(id, kVal, kLen) {
  const fiipCloudVarList = fiipCloudVar_getVarList(id);
  if (!fiipCloudVarList[kVal]) {
    fiipCloudVarList[kVal] = {};
  }
  return fiipCloudVarList[kVal];
}
function fiipCloudVar_setActual(id, kVal, kLen, vVal, vLen) {
  const cloudVar = fiipCloudVar_get(id, kVal, kLen);
  const listener = ActualListeners[id + kVal];
  let hadChange = 0;

  if (cloudVar.actualLen !== vLen) {
    hadChange = 1;
    cloudVar.actualLen = vLen;
    cloudVar.actualVal = vVal;
  } else {
    if (memcmp(cloudVar.actualVal, vVal, vLen) !== 0) {
      hadChange = 1;
      cloudVar.actualVal = vVal;
    }
  }

  if (listener) {
    if (hadChange === 1) {
      listener.fun(id, cloudVar);
    }
  }
}
function fiipCloudVar_setTarget(id, kVal, kLen, vVal, vLen) {
  const cloudVar = fiipCloudVar_get(id, kVal, kLen);
  const listener = TargetListeners[id + kVal];
  let hadChange = 0;

  if (cloudVar.targetLen !== vLen) {
    hadChange = 1;
    cloudVar.targetLen = vLen;
    cloudVar.targetVal = vVal;
  } else {
    if (memcmp(cloudVar.targetVal, vVal, vLen) !== 0) {
      hadChange = 1;
      cloudVar.targetVal = vVal;
    }
  }

  if (listener) {
    if (hadChange === 1) {
      listener.fun(id, cloudVar);
    }
  }
}
function fiipCloudVar_getActual(id, kVal, kLen) {
  const cloudVar = fiipCloudVar_get(id, kVal, kLen);
  return cloudVar.actualVal;
}
function fiipCloudVar_getTarget(id, kVal, kLen) {
  const cloudVar = fiipCloudVar_get(id, kVal, kLen);
  return cloudVar.targetVal;
}

const Var = {
  init: fiipCloudVar_init,
  onActualChange: fiipCloudVar_onActualChange, //user
  onTargetChange: fiipCloudVar_onTargetChange, //user
  getVarList: fiipCloudVar_getVarList, //user
  get: fiipCloudVar_get, //user
  setActual: fiipCloudVar_setActual,
  setTarget: fiipCloudVar_setTarget,
  getActual: fiipCloudVar_getActual, //user
  getTarget: fiipCloudVar_getTarget, //user
};
module.exports = Var;
